home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
101-125
/
118
/
empire
/
src
/
source.zoo
/
util.d
< prev
Wrap
Text File
|
1987-12-02
|
15KB
|
677 lines
#include:util.g
#include:libraries/dos.g
#empire.g
#empfunc.g
/*
* readLine - read a line, terminating with a \e.
*/
proc readLine(*char buffer; uint length)bool:
ulong gotLength;
bool result;
gotLength := LineRead(Chin, buffer, length - 1);
if gotLength = LINE_EOF then
pretend(ioerror(Chin), void);
result := false;
else
if gotLength >= length then
gotLength := length - 1;
fi;
(buffer + gotLength)* := '\e';
result := true;
fi;
result
corp;
/*
* ask - ask a question, return true for 'y' answer.
*/
proc ask(*char question)bool:
char answer;
while
write(PromptOut; question);
if not readln(Chin; answer) then
pretend(ioerror(Chin), void);
if not readln(Chin;) then
pretend(ioerror(Chin), void);
fi;
answer := 'n';
fi;
answer ~= 'y' and answer ~= 'n'
do
writeln(PromptOut; "Please answer with 'y' or 'n'");
od;
answer = 'y'
corp;
/*
* lookupCommand - look up a command in a table of command names.
* If the name is unambiguous, return it's code number (2 - n + 2).
* Return 0 if the command is not found, 1 if it's ambiguous.
*/
proc lookupCommand(*char commandList, command)uint:
*char p;
uint i, which, found;
i := 2;
found := 0;
while commandList* ~= '\e' do
p := command;
while p* = commandList* and p* ~= '\e' do
p := p + 1;
commandList := commandList + 1;
od;
if p* = '\e' then
which := i;
found := found + 1;
fi;
while commandList* ~= '\e' do
commandList := commandList + 1;
od;
commandList := commandList + 1;
i := i + 1;
od;
if found = 0 then
0
elif found = 1 then
which
else
1
fi
corp;
/*
* writeDate - write a date from the given time. Note: the date is in seconds.
*/
proc writeDate(ulong date)void:
[25] char buffer;
ConvTime(date, &buffer[0]);
write(Chout; &buffer[0]);
corp;
/*
* transRow - translate user row number to absolute row number.
*/
proc transRow(int r)uint:
r := r + ThisCountry*.c_centerRow;
while r < 0 do
r := r + World.w_rows;
od;
r % World.w_rows
corp;
/*
* transCol - translate user column number to absolute column number.
*/
proc transCol(int c)uint:
c := c + ThisCountry*.c_centerCol;
while c < 0 do
c := c + World.w_columns;
od;
c % World.w_columns
corp;
/*
* err - print an error message.
*/
proc err(*char mess)void:
writeln(Chout; "*** ", mess, " ***");
corp;
/*
* getDesigName - return the full string for a sector type name.
*/
proc getDesigName(SectorType_t desig)*char:
case desig
incase s_water:
"sea"
incase s_mountain:
"mountain"
incase s_wilderness:
"wilderness"
incase s_sanctuary:
"sanctuary"
incase s_capital:
"capital"
incase s_urban:
"urban area"
incase s_defense:
"defense plant"
incase s_industry:
"shell industry"
incase s_ironMine:
"mine"
incase s_goldMine:
"gold mine"
incase s_harbour:
"harbor"
incase s_warehouse:
"warehouse"
incase s_technical:
"technical center"
incase s_fortress:
"fortress"
incase s_airport:
"airport"
incase s_research:
"research laboratory"
incase s_highway:
"highway"
incase s_radar:
"radar station"
incase s_weather:
"weather station"
incase s_bridgeHead:
"bridge head"
incase s_bridgeSpan:
"bridge span"
incase s_bank:
"bank"
incase s_exchange:
"exchange"
default:
"???? unknown desig ????"
esac
corp;
/*
* getItemName - return the full string name for a commodity.
*/
proc getItemName(ItemType_t item)*char:
case item
incase it_civilians:
"civilians"
incase it_military:
"military"
incase it_shells:
"shells"
incase it_guns:
"guns"
incase it_planes:
"planes"
incase it_ore:
"ore"
incase it_bars:
"bars"
default:
"??? unknown item ???"
esac
corp;
/*
* getShipName - return the full string name for a ship.
*/
proc getShipName(ShipType_t typ)*char:
case typ
incase st_PTBoat:
"PT boat"
incase st_mineSweeper:
"minesweeper"
incase st_destroyer:
"destroyer"
incase st_submarine:
"submarine"
incase st_freighter:
"freighter"
incase st_tender:
"tender"
incase st_battleship:
"battleship"
incase st_carrier:
"carrier"
default:
"??? unknown ship ???"
esac
corp;
/*
* getIndex - return the index of a character in a character array.
*/
proc getIndex(*char types; char typ)uint:
uint index;
index := 0;
while types* ~= typ do
if types* = '\e' then
abort("getIndex: typ not found in types");
fi;
types := types + sizeof(char);
index := index + 1;
od;
index
corp;
/*
* getShipIndex - return the index of the given ship type code.
*/
proc getShipIndex(char shipType)uint:
getIndex(&ShipChar[0], shipType)
corp;
/*
* getItemIndex - return the index of the given item type code.
*/
proc getItemIndex(char itemType)uint:
getIndex(&ItemChar[0], itemType)
corp;
/*
* min - return the minimum of two ints.
*/
proc min(int a, b)int:
if a < b then a else b fi
corp;
/*
* umin - return the minimum of two uints.
*/
proc umin(uint a, b)uint:
if a < b then a else b fi
corp;
/*
* updateTimer - Updates time limit counter, returns 'true' if we should quit
*/
proc updateTimer()bool:
ulong now, dt;
weatherUpdate();
now := CurrentTime();
if ThisCountryNumber = DEITY then
false
elif ThisCountry*.c_last / (24 * 60 * 60) ~= now / (24 * 60 * 60) then
/* it's now the next day - reset timer */
ThisCountry*.c_last := now;
ThisCountry*.c_timer := World.w_maxConnect;
false
else
if ThisCountry*.c_timer < (now - ThisCountry*.c_last) / 60 then
/* he's been here too long! - he should go away */
ThisCountry*.c_timer := 0;
true
else
dt := (now - ThisCountry*.c_last) / 60;
if dt >= 1 then
ThisCountry*.c_timer := ThisCountry*.c_timer - dt;
ThisCountry*.c_last := ThisCountry*.c_last + dt * 60;
fi;
false
fi
fi
corp;
/*
* resetTimer - Resets the timer when you enter the program if you haven't
* been in the program since 12 midnight. Also recalculate BTUS.
* Returns 'true' if you are out of time for the day.
*/
proc resetTimer()bool:
Sector_t s;
ulong now;
weatherUpdate();
now := CurrentTime();
if ThisCountryNumber = DEITY then
ThisCountry*.c_timer := 999;
ThisCountry*.c_last := now;
false
else
readSector(0, 0, s);
if updateSector(0, 0, s) then
writeSector(0, 0, s);
fi;
/* Check to see if we changed days since the last access */
if ThisCountry*.c_last / (24 * 60 * 60) ~= now / (24 * 60 * 60) then
ThisCountry*.c_timer := World.w_maxConnect;
fi;
ThisCountry*.c_last := now;
ThisCountry*.c_timer = 0
fi
corp;
/*
* accessSector - read a sector, update it, and write it back out if needed.
* The caller need not write it out again, and if he wants to, he should
* use readSector/writeSector to save on disk I/O.
*/
proc accessSector(int row, col; Sector_t s)void:
readSector(row, col, s);
if updateSector(row, col, s) then
writeSector(row, col, s);
fi;
corp;
/*
* accessShip - read a ship, update it, and write it out if needed.
*/
proc accessShip(uint shipNumber; Ship_t sh)void:
readShip(shipNumber, sh);
if updateShip(shipNumber, sh) then
writeShip(shipNumber, sh);
fi;
corp;
/*
* getBundleSize - get the size of the storage bundle for given types.
*/
proc getBundleSize(SectorType_t sectorType; ItemType_t thingType)uint:
if sectorType = s_warehouse then
if thingType = it_shells or thingType = it_guns or
thingType = it_ore then
10
else
1
fi
elif sectorType = s_urban then
if thingType = it_civilians then 10 else 1 fi
elif sectorType = s_bank then
if thingType = it_bars then 4 else 1 fi
else
1
fi
corp;
/*
* readQuan - return the current quantity of the indicated commodity at the
* passed sector.
*/
proc readQuan(Sector_t s; ItemType_t what)uint:
getBundleSize(s.s_type, what) * s.s_quantity[what]
corp;
/*
* writeQuan - write the given quantity of the indicated commodity to the
* passed sector. Any excess is discarded silently.
*/
proc writeQuan(Sector_t s; ItemType_t what; uint quan)void:
char desig;
s.s_quantity[what] := min(127, quan / getBundleSize(s.s_type, what));
corp;
/*
* getTransportCost - get the transportion cost of moving the given quantity
* of the given thing out of the given type of sector. Note that the
* cost is rounded up to the next shipment bundle size. We assume that
* the quantity is already rounded up to the storage bundle size.
*/
proc getTransportCost(SectorType_t sectorType; ItemType_t thingType;
uint quantity)uint:
uint bundleSize;
bundleSize := getBundleSize(sectorType, thingType);
case thingType
incase it_civilians:
/* civMob mobility per 5 bundles of civilians */
(quantity + 4 * bundleSize) / (5 * bundleSize) * World.w_civMob
incase it_military:
/* milMob mobility per 5 bundles of military */
(quantity + 4 * bundleSize) / (5 * bundleSize) * World.w_milMob
incase it_shells:
/* shellMob mobility per 5 bundles of shells */
(quantity + 4 * bundleSize) / (5 * bundleSize) * World.w_shellMob
incase it_guns:
/* gunMob mobility per bundle of guns */
quantity / bundleSize * World.w_gunMob
incase it_planes:
/* planeMob mobility per bundle of planes */
quantity / bundleSize * World.w_planeMob
incase it_ore:
/* World.w_oreMob mobility per 5 bundles of ore */
(quantity + 4 * bundleSize) / (5 * bundleSize) * World.w_oreMob
incase it_bars:
/* barMob mobility per bar, except barMob / 2 per bar leaving a bank */
if sectorType = s_bank then
quantity * World.w_barMob / 2
else
quantity * World.w_barMob
fi
default:
err("unknown item type in 'getTransportCost'");
quantity
esac
corp;
/*
* getTerrainCost - scale the cost for movement onto the given sector.
*/
proc getTerrainCost(Sector_t s; ulong cost)ulong:
if s.s_type = s_highway or s.s_type = s_bridgeSpan then
cost * (100 - s.s_efficiency) / 100
elif s.s_type = s_mountain then
cost * World.w_mountMob
elif s.s_type = s_wilderness then
cost * World.w_wildMob
else
cost * World.w_defMob
fi
corp;
/*
* adjustForNewWorkers - new workers have just been moved into the sector -
* fix it up so as to not loose mobility or gain work.
*/
proc adjustForNewWorkers(Sector_t s; ItemType_t what; uint quantity)void:
ulong now, dt, dt2, iwork;
uint workForce;
[25] char buff;
/* we have to keep any work pending in the target
sector correct. We do this by moving its last
update time forward as required. */
/* workforce BEFORE the new guys added: */
workForce :=
if what = it_civilians then
quantity + s.s_quantity[it_military] / 5
else
s.s_quantity[it_civilians] + quantity / 5
fi;
now := CurrentTime();
if s.s_lastUpdate = 0 or s.s_lastUpdate > now or
s.s_lastUpdate < now - (7 * 24 * 60 * 60) and workForce ~= 0 then
if s.s_lastUpdate ~= 0 then
ConvTime(now, &buff[0]);
write(LogChannel; "*** 'adjustForNewWorkers': now = ", &buff[0]);
ConvTime(s.s_lastUpdate, &buff[0]);
writeln(LogChannel; ", lastUpdate = ", &buff[0]);
fi;
s.s_lastUpdate := now / (60 * 30) * (60 * 30);
fi;
dt := (now - s.s_lastUpdate) / (60 * 30);
/* work pending in the sector: */
iwork := workForce * dt;
/* workforce AFTER the new guys added: */
workForce := s.s_quantity[it_civilians] + s.s_quantity[it_military] / 5;
/* time they would have taken to do the work: */
dt2 := iwork / workForce;
/* add mobility since it's not dependent on iwork: */
s.s_mobility := min(127, s.s_mobility + (dt - dt2));
/* and crank the update time forward: */
s.s_lastUpdate := (now / (60 * 30) - dt2) * (60 * 30);
corp;
/*
* getTechFactor - return the country's current technology factor.
* (range returned is 0 - 99)
*/
proc getTechFactor(uint country)uint:
ulong level;
level := Country[country].c_techLevel;
(250000 + 6175 * level) / (10000 + 61 * level)
corp;
/*
* getDefender - return the coordinates of a defending fort.
*/
proc getDefender(int r, c; Sector_t s; *int pRow, pCol)void:
uint defender;
defender := s.s_defender;
pRow* := r + (defender >> 4) - 8;
pCol* := c + (defender & 0xf) - 8;
corp;
/*
* putDefender - store a defender offset value.
*/
proc putDefender(int r, c; Sector_t s; int rDefender, cDefender)void:
s.s_defender := make(rDefender + 8 - r, uint) << 4 |
make(cDefender + 8 - c, uint);
corp;
/*
* findDistance - return the square of the distance between two locations.
*/
proc findDistance(int r1, c1, r2, c2)uint:
uint d1, d2;
d1 := |(r1 - r2);
while d1 >= World.w_rows do
d1 := d1 - World.w_rows;
od;
if d1 > World.w_rows / 2 then
d1 := World.w_rows - d1;
fi;
d2 := |(c1 - c2);
while d2 >= World.w_columns do
d2 := d2 - World.w_columns;
od;
if d2 > World.w_columns / 2 then
d2 := World.w_columns - d2;
fi;
d1 * d1 + d2 * d2
corp;
/*
* getItemCost - return the cost per unit of various items.
*/
proc getItemCost(ItemType_t what)uint:
case what
incase it_shells:
World.w_shellCost
incase it_guns:
World.w_gunCost
incase it_planes:
World.w_planeCost
incase it_bars:
World.w_barCost
default:
1
esac
corp;
/*
* readShipQuan - read the quantity of stuff the ship is carrying.
*/
proc readShipQuan(Ship_t sh; ItemType_t what)uint:
case what
incase it_civilians:
incase it_military:
sh.sh_crew
incase it_shells:
sh.sh_shells
incase it_guns:
sh.sh_guns
incase it_planes:
sh.sh_planes
incase it_ore:
sh.sh_ore
incase it_bars:
sh.sh_bars
default:
err("unknown item in 'readShipQuan'");
0
esac
corp;
/*
* writeShipQuan - write the quantity of stuff to the ship.
*/
proc writeShipQuan(Ship_t sh; ItemType_t what; uint quantity)void:
case what
incase it_civilians:
incase it_military:
sh.sh_crew := quantity;
incase it_shells:
sh.sh_shells := quantity;
incase it_guns:
sh.sh_guns := quantity;
incase it_planes:
sh.sh_planes := quantity;
incase it_ore:
sh.sh_ore := quantity;
incase it_bars:
sh.sh_bars := quantity;
default:
err("unknown item in 'writeShipQuan'");
esac;
corp;
/*
* getNavCost - return the cost of navigating the given ship type one
* sector orthogonally. The result is x 10.
*/
proc getNavCost(ShipType_t shipType)uint:
uint tf;
tf := getTechFactor(ThisCountryNumber);
make(World.w_shipSpeed[shipType], ulong) *
(10000 / tf * 2) / (10000 / tf + 100) / 10
corp;